`include "defines.v"
module ysyx_210448_CSR(
    input wire clk,
	input wire rst,
    input wire if_fetched,
    input wire wb_fetched,
    input wire exe_fetched,
    input wire exe_pc_write,
    input wire if_ar_hand,
    input wire wb_read,
    input wire mem_fetched,
    input wire mem_read,
    input wire [63:0] if_pc,
    input wire [63:0] exe_pc_add,
    input wire [31:0] wb_inst,
	input wire [11:0] id_csr,
    input wire [11:0] wb_csr,
    input wire wb_csr_write,
	input wire id_csr_read,
    input wire [4:0] id_rs1,
    input wire [4:0] wb_rd,
    input wire [63:0] mtimecmp_data,
    input wire mtimecmp_open,
    input wire [63:0] mtime_data,
    input wire mtime_open,
    input wire clint_skip,
    input wire [63:0] csr_data,
    input wire [63:0]pc,
    output reg [63:0]id_t,
	output reg [63:0] mstatus,
    output reg [63:0] sstatus,	
    output reg [63:0] mepc,
    output reg [63:0] mtvec,
    output reg [63:0] mcause,
	output reg [63:0] mip,
	output reg [63:0] mie,
    output reg [63:0] mcycle,
    output reg [63:0] mscratch,
    output wire id_csr_skip,
    output reg [63:0] mcause_data,
    output reg [63:0] mstatus_data,
    output reg [63:0] rmstatus,
    output reg [63:0] mhartid,
    output reg [63:0] csr_pc_add,
    output reg csr_pc_write,
    output wire [63:0] mtimecmp,
    output wire [63:0] mtime,
    output wire clock_interrupt
    );
//wire clock_interrupt;

//包含mtime,mtimecmp
ysyx_210448_clint ysyx_210448_clint(
.clk(clk),
.rst(rst),
.mtimecmp_data(mtimecmp_data),
.mtimecmp_open(mtimecmp_open),
.mtime_data(mtime_data),
.mtime_open(mtime_open),
.mcause_data(mcause_data),
.mie(mie),
.mstatus(mstatus),
.mtime(mtime),
.mtimecmp(mtimecmp),
.clock_interrupt(clock_interrupt)
);

reg interrupt_ready1;
reg interrupt;
reg pc_write_ready;
reg [63:0] pc_add_ready;

reg wb_stage;
reg [63:0] mepc_exe;
reg pc_jump;
always @(posedge clk) begin
    if((mem_fetched)&&(exe_pc_write))
    mepc_exe<=exe_pc_add;
    else if(if_fetched)
    mepc_exe<=if_pc+4;
    if((wb_fetched)||(wb_read))
    wb_stage<=1'b1;
    else if(if_ar_hand)
    wb_stage<=1'b0;
    if(clock_interrupt)
    interrupt_ready1<=1'b1;
    else if(if_fetched)
    interrupt_ready1<=1'b0;
end

assign interrupt=(wb_stage)?((clock_interrupt)?clock_interrupt:interrupt_ready1):0;


always @(posedge clk) begin
    if(interrupt)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<={mtvec[63:2],2'b0};
    end
    else if((wb_csr_write)&&wb_csr==12'h302)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<=mepc;
    end
    else if((wb_csr_write)&&wb_csr==12'h000)
    begin
    csr_pc_write<=1'b1;
    csr_pc_add<={mtvec[63:2],2'b0};
    end
    else if(if_fetched)
    begin
    csr_pc_write<=1'b0;
    csr_pc_add<=64'b0;
    end
end






reg mstatus_mie;
reg mstatus_mpie;
wire [1:0] mpp=2'b11;
reg [1:0] mstatus_fs;
always @(posedge clk) 
begin
  mcycle<=mcycle+1;//mcycle赋值
  if (rst==1'b1) 
  begin
	mstatus<=`ZERO_WORD;
    mepc<=`ZERO_WORD;
    mtvec<=`ZERO_WORD;
    mcause<=`ZERO_WORD;
    sstatus<=64'b0;
    mcycle<=`ZERO_WORD;
    mie<=`ZERO_WORD;
    mscratch<=`ZERO_WORD;
    mip<=`ZERO_WORD;
    mhartid<=`ZERO_WORD;
  end
  else
  begin
  if(wb_fetched&&wb_csr_write)
  begin
    case(wb_csr)
    12'h000:
    begin 
    mepc<=pc;
    mcause<=mcause_data;
    mstatus_mpie<=mstatus_mie;
    mstatus<={{mstatus[63:13]},{mpp[1:0]},{mstatus[10:8]},{mstatus_mie},{mstatus[6:4]},{1'b0},{mstatus[2:0]}};
    mstatus_fs<=mstatus[14:13];
    //pc_write=1'b1;
    //pc_add={mtvec[63:2],2'b0};
    end
    12'h305:mtvec<={csr_data[63:2],2'b0};
    12'h300:
    begin 
    if(id_rs1!=5'b0) begin 
    mstatus<={{csr_data[13]},{csr_data[62:0]}}; 
    sstatus<={{csr_data[13]},{csr_data[62:15]},{csr_data[14:13]},{13{1'b0}}};   
    if(((id_rs1!=5'b0)&&(wb_rd!=5'b0))||((mstatus[13])&&(wb_rd==5'b0))) begin
    rmstatus<=csr_data;
    mstatus_mie<=csr_data[3]; 
    mstatus_fs<=csr_data[14:13];
    mstatus_mpie<=csr_data[7]; 
    end  
    end 
    end
    12'h341:if(id_rs1!=5'b0)mepc<=csr_data;
    12'h344:mip<=csr_data;
    12'h304:mie<=csr_data;
    12'h342:mcause<=csr_data;
    12'h340:mscratch<=csr_data;
    12'h302:
    begin 
    mstatus<=(interrupt)?
    rmstatus:
    ({{mstatus_fs[0]},{rmstatus[62:15]},{mstatus_fs},{2{1'b0}},{rmstatus[10:8]},{1'b1},{rmstatus[6:4]},{mstatus_mpie},rmstatus[2:0]});
    end
    12'hf14:mhartid<=csr_data;
    default:;
    endcase
  end
  if(clock_interrupt)
  begin
    if(wb_inst!=32'b0)
    begin
    //mstatus_mie<=mstatus[3]; 
    rmstatus<=mstatus; 
    mstatus_fs<=mstatus[14:13];
    mstatus_mpie<=mstatus[3];
    mepc<=(wb_csr==12'h302)?mepc:mepc_exe;
    mstatus_mpie<=mstatus[3];
    mcause<=mcause_data;
    mip<={{mip[63:8]},{1'b1},{mip[6:0]}};
    mstatus<=(wb_csr==12'h302)?rmstatus:((wb_csr==12'h300)?
    {{csr_data[63:13]},{mpp[1:0]},{csr_data[10:8]},{csr_data[3]},{csr_data[6:4]},{1'b0},{csr_data[2:0]}}
    :{{mstatus[63:13]},{mpp[1:0]},{mstatus[10:8]},{mstatus[3]},{mstatus[6:4]},{1'b0},{mstatus[2:0]}});
    end
  end
   end
end

always @(*) begin
   if (rst == 1'b1) begin
	id_t=`ZERO_WORD;
    id_csr_skip=1'b0; 
    end
	else if(id_csr_read==1'b1) 
    begin
    case(id_csr)
      12'h000:id_t=mepc;
	  12'h300:id_t=mstatus;  
      12'h341:id_t=mepc; 
      12'h305:id_t=mtvec;
      12'h342:id_t=mcause;
      12'h344:id_t=mip;
      12'h304:id_t=mie;
      12'hf14:id_t=mhartid;
      12'h340:id_t=mscratch;
      12'hb00:begin 
          id_t=mcycle;
          id_csr_skip=1'b1; 
          end
	default:id_t=`ZERO_WORD;
	endcase
    end
	else 
    begin
    id_csr_skip=1'b0;
	id_t=`ZERO_WORD; 
    end
end	


	
endmodule
